/**
 * $Id: GdDocument.java,v 1.2 2011-01-31 12:13:34 david Exp $
 * Copyright (c) 2010, Gaudenz Alder, David Benson
 */
package com.kg.rails.component.editor.io.gd;

import com.kg.rails.component.editor.util.EditorPoint;

import java.io.BufferedReader;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.List;

/**
 * This class is a representation of a GD file.<br/>
 * Allows access to the nodes and edges of the graph.
 */
public class GdDocument {
    /**
     * Represents the different states in the parse of a file.
     */
    public enum mxGDParseState {
        START, PARSING_NODES, PARSING_EDGES
    }

    private List<GdNode> nodes = new ArrayList<GdNode>();

    private List<GdEdge> edges = new ArrayList<GdEdge>();

    /**
     * @return Returns the list of edges.
     */
    public List<GdEdge> getEdges() {
        return edges;
    }

    /**
     * @return Returns the list of nodes.
     */
    public List<GdNode> getNodes() {
        return nodes;
    }

    public void setEdges(List<GdEdge> edges) {
        this.edges = edges;
    }

    public void setNodes(List<GdNode> nodes) {
        this.nodes = nodes;
    }

    /**
     * Parses the String with the file content and loads into the document,
     * the data of nodes and edges.
     *
     * @param gd String with the file content.
     */
    public void parse(String gd) {
        gd = gd.trim();
        BufferedReader br = new BufferedReader(new StringReader(gd));
        mxGDParseState state = mxGDParseState.START;
        try {
            String line = br.readLine();
            while (line != null) {
                switch (state) {
                    case START: {
                        if (line.startsWith("# Nodes")) {
                            state = mxGDParseState.PARSING_NODES;
                        } else {
                            throw new Exception("Error in parsing");
                        }
                        break;
                    }
                    case PARSING_NODES: {
                        if (line.startsWith("# Edges")) {
                            state = mxGDParseState.PARSING_EDGES;
                        } else if (!line.equals("")) {
                            String[] items = line.split(",");
                            if (items.length != 5) {
                                throw new Exception("Error in parsing");
                            } else {
                                double x = Double.valueOf(items[1]);
                                double y = Double.valueOf(items[2]);
                                double width = Double.valueOf(items[3]);
                                double height = Double.valueOf(items[4]);
                                GdNode node = new GdNode(items[0],
                                        new EditorPoint(x, y), new EditorPoint(width,
                                        height));
                                nodes.add(node);
                            }
                        }
                        break;
                    }
                    case PARSING_EDGES: {
                        if (!line.equals("")) {
                            String[] items = line.split(",");
                            if (items.length != 2) {
                                throw new Exception("Error in parsing");
                            } else {
                                String source = items[0];
                                String target = items[1];
                                GdEdge edge = new GdEdge(source, target);
                                edges.add(edge);
                            }
                        }
                        break;
                    }
                }

                line = br.readLine();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * @return Returns the String representation of the document.
     */
    public String getDocumentString() {
        StringBuilder buf = new StringBuilder("# Nodes\n");

        for (GdNode node : nodes) {
            buf.append(node.getNodeString());
            buf.append("\n");
        }

        buf.append("# Edges\n");

        for (GdEdge edge : edges) {
            buf.append(edge.getEdgeString());
            buf.append("\n");
        }

        return buf.toString();
    }
}
